package deibay.server.frontend.communication.clients;


import java.io.IOException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import deibay.DeibayLogger;
import deibay.messages.Message;
import deibay.messages.SendAdvertiseMsg;
import deibay.network.IClientCommunicator;
import deibay.server.frontend.FrontEndCore;
import deibay.users.User;
import deibay.util.IClosable;
import deibay.util.Pair;

public class ClientsManager implements IClosable{

	private Hashtable<String, IClientCommunicator> sessions = null;
	private ClientSessionActivity tClientsConnections = null;	
	private SocketServer server = null;		
	private UDPService udpService = null;
	
	public ClientsManager()
	{
		sessions = new Hashtable<String, IClientCommunicator>();			
	}

	public void init()
	{
		server = new SocketServer();
		udpService = new UDPService();
		tClientsConnections = new ClientSessionActivity(sessions);		
		initializeThreads();
	}	

	private void initializeThreads() 
	{
		new Thread(server).start();		
		new Thread(tClientsConnections).start();				
	}

	public synchronized void addLoggedUser(User user, IClientCommunicator communicator)
	{		
		synchronized(sessions) {
			if(sessions.get(user.getId())==null)
			{
				sessions.put(user.getId(), communicator);
				DeibayLogger.getInstance().getLog().log(Level.WARNING, "Foi adicionada uma sessao ao utilizador '"+user.getId()+"'.\n");
				if (sessions.size() > 0)
				{
					sessions.notifyAll();
				}
			}
		}			
	}
	
	public synchronized void removeLoggedUser(User user)
	{
		synchronized(sessions)
		{
			IClientCommunicator communicator = this.sessions.remove(user.getId());
			communicator.close();
		}			
		DeibayLogger.getInstance().getLog().log(Level.INFO, "Removido o utilizador "+user.getId()+".\n");
	}
	
	public void sendMessageToUser(String user, Message message)
	{			
		IClientCommunicator communicator = this.sessions.get(user);
		try {				
			DeibayLogger.getInstance().getLog().log(Level.INFO, "A enviar mensagem "+message.toString()+" ao user "+user);
			communicator.send(message);
		}catch(IOException exception)
		{
			DeibayLogger.getInstance().getLog().log(Level.SEVERE, "Erro ao enviar mensagem no clientsManager");			
		}
	}

	public void sendAdvertise(SendAdvertiseMsg message) {		
		udpService.sendMessage(message);
	}

	public void close() {
		tClientsConnections.close();	
		server.close();
		udpService.close();
		synchronized(sessions)
		{
			for(IClientCommunicator communicator: sessions.values())
				communicator.close();
		}		 
	}
	
	public Set<String> getLoggedUsers()
	{
		return this.sessions.keySet();
	}
}
